package com.ruoyi.flow.controller;

import com.ruoyi.common.core.domain.BaseResponse;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.core.web.controller.BaseController;
import com.ruoyi.common.core.web.page.TableDataInfo;
import com.ruoyi.common.security.annotation.RequiresPermissions;
import com.ruoyi.common.security.utils.SecurityUtils;
import com.ruoyi.flow.api.domain.WarmFlowInteractiveType;
import com.ruoyi.flow.service.ExecuteService;
import com.ruoyi.flow.service.HhDefService;
import com.ruoyi.flow.vo.FlowHisTaskVo;
import com.ruoyi.flow.vo.FlowTaskVo;
import com.ruoyi.system.api.domain.SysDept;
import com.ruoyi.system.api.domain.SysRole;
import com.ruoyi.system.api.domain.SysUser;
import com.warm.flow.core.FlowFactory;
import com.warm.flow.core.constant.FlowCons;
import com.warm.flow.core.entity.*;
import com.warm.flow.core.enums.CooperateType;
import com.warm.flow.core.enums.NodeType;
import com.warm.flow.core.enums.UserType;
import com.warm.flow.core.service.*;
import com.warm.flow.core.utils.StreamUtils;
import com.warm.flow.orm.entity.FlowHisTask;
import com.warm.flow.orm.entity.FlowTask;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * 流程实例Controller
 *
 * @author hh
 * @date 2023-04-18
 */
@Validated
@RestController
@RequestMapping("/execute")
public class ExecuteController extends BaseController {
    @Resource
    private TaskService taskService;

    @Resource
    private NodeService nodeService;

    @Resource
    private InsService insService;

    @Resource
    private ExecuteService executeService;

    @Resource
    private HhDefService hhDefService;

    /**
     * 分页待办任务列表
     */
    @RequiresPermissions("flow:execute:toDoPage")
    @GetMapping("/toDoPage")
    public TableDataInfo toDoPage(FlowTask flowTask) {
        SysUser sysUser = SecurityUtils.getLoginUser().getSysUser();
        List<String> permissionList = permissionList(String.valueOf(sysUser.getUserId()), "dept:" + sysUser.getDeptId(), sysUser);
        flowTask.setPermissionList(permissionList);
        startPage();
        List<FlowTaskVo> list = executeService.toDoPage(flowTask);
        return getDataTable(list);
    }

    /**
     * 分页已办任务列表
     */
    @RequiresPermissions("flow:execute:donePage")
    @GetMapping("/donePage")
    public TableDataInfo donePage(FlowHisTask flowHisTask) {
        startPage();
        SysUser sysUser = SecurityUtils.getLoginUser().getSysUser();
        List<String> permissionList = permissionList(String.valueOf(sysUser.getUserId()), "dept:" + sysUser.getDeptId(), sysUser);
        flowHisTask.setPermissionList(permissionList);
        List<FlowHisTaskVo> list = executeService.donePage(flowHisTask);
        return getDataTable(list);
    }

    /**
     * 查询已办任务历史记录
     */
    @RequiresPermissions("flow:execute:doneList")
    @GetMapping("/doneList/{instanceId}")
    public BaseResponse<List<HisTask>> doneList(@PathVariable("instanceId") Long instanceId) {
        List<HisTask> flowHisTasks = executeService.selectHisTask(new FlowHisTask().setInstanceId(instanceId));
        return BaseResponse.ok(flowHisTasks);
    }

    /**
     * 根据taskId查询代表任务
     *
     * @param taskId 任务id
     * @return 待办任务
     */
    @GetMapping("/getTaskById/{taskId}")
    public BaseResponse<Task> getTaskById(@PathVariable("taskId") Long taskId) {
        return BaseResponse.ok(taskService.getById(taskId));
    }

    /**
     * 查询跳转任意节点列表
     */
    @RequiresPermissions("flow:execute:doneList")
    @GetMapping("/anyNodeList/{instanceId}/{nodeCode}")
    public BaseResponse<List<Node>> anyNodeList(@PathVariable("instanceId") Long instanceId
            , @PathVariable("nodeCode") String nodeCode) {
        Instance instance = insService.getById(instanceId);
        Node node = nodeService.getOne(FlowFactory.newNode().setDefinitionId(instance.getDefinitionId()).setNodeCode(nodeCode));
        if (FlowCons.SKIP_ANY_N.equals(node.getSkipAnyNode())) {
            return BaseResponse.ok();
        }
        List<Node> nodeList = nodeService.list(FlowFactory.newNode().setDefinitionId(instance.getDefinitionId()));
        nodeList = StreamUtils.filter(nodeList, n -> (NodeType.isBetween(n.getNodeType())
                || NodeType.isEnd(n.getNodeType())) && !nodeCode.equals(n.getNodeCode()));
        return BaseResponse.ok(nodeList);
    }

    /**
     * 处理非办理的流程交互类型
     *
     * @param warmFlowInteractiveType 要转办用户
     * @return 是否成功
     */
    @PostMapping("/interactiveType")
    public BaseResponse<Boolean> interactiveType(WarmFlowInteractiveType warmFlowInteractiveType) {
        return BaseResponse.ok(hhDefService.interactiveType(warmFlowInteractiveType));
    }

    /**
     * 交互类型可以选择的用户
     *
     * @param warmFlowInteractiveType 交互类型请求类
     * @return 是否成功
     */
    @GetMapping("/interactiveTypeSysUser")
    public TableDataInfo interactiveTypeSysUser(WarmFlowInteractiveType warmFlowInteractiveType) {
        startPage();
        SysUser currentUser = SecurityUtils.getLoginUser().getSysUser();
        Long userId = currentUser.getUserId();
        Integer operatorType = warmFlowInteractiveType.getOperatorType();
        List<SysUser> list;
        Long taskId = warmFlowInteractiveType.getTaskId();
        if (!Objects.equals(CooperateType.REDUCTION_SIGNATURE.getKey(), operatorType)) {
            list = executeService.selectNotUserList(warmFlowInteractiveType);
        } else {
            list = executeService.selectUserList(warmFlowInteractiveType);
            list = StreamUtils.filter(list, sysUser -> !Objects.equals(userId, sysUser.getUserId()));
        }
        return getDataTable(list);
    }

    /**
     * 获取权限
     *
     * @param userId  用户编号
     * @param deptId  部门编号
     * @param sysUser 登陆用户
     * @return 权限列表
     */
    private List<String> permissionList(String userId, String deptId, SysUser sysUser) {
        List<SysRole> roles = sysUser.getRoles();
        List<String> permissionList = StreamUtils.toList(roles, role -> "role:" + role.getRoleId());
        permissionList.add(userId);
        permissionList.add(deptId);
        logger.info("当前用户所有权限[{}]", permissionList);
        return permissionList;
    }
}
